package com.aica.config;


import com.aica.filter.CustomAuthenticationFilter;
import com.aica.filter.JwtAuthenticationFilter;
import com.aica.handler.CustomAccessDeniedHandler;
import com.aica.handler.LoginFailureHandler;
import com.aica.handler.LoginSuccessHandler;
import com.aica.point.CustomizeAuthenticationEntryPoint;
import com.aica.service.MyUserDetailsService;
import com.aica.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.annotation.Resource;


/**
 * @author yly
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled =true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private LoginFailureHandler loginFailureHandler;

    @Autowired
    private LogoutSuccessHandler logoutHandler;

    @Autowired
    private CustomizeAuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private CustomAccessDeniedHandler accessDeniedHandler;



    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()//关闭csrf
                //基于token，所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .addFilter(new JwtAuthenticationFilter(authenticationManager(),redisUtil))


                .formLogin()
                //.loginProcessingUrl("/user/login")
                // 登录成功
                //.successHandler(loginSuccessHandler)
                // 登录失败
                //.failureHandler(loginFailureHandler)
                .and()
                // 注销成功
                .logout()
                .logoutUrl("/user/logout")
                .logoutSuccessHandler(logoutHandler)

                .and()
                // 异常拦截
                .exceptionHandling()
                //未登录请求资源
                .authenticationEntryPoint(authenticationEntryPoint)
                //权限不足
                .accessDeniedHandler(accessDeniedHandler)
                .and()
                .authorizeRequests()//该方法所返回的对象的方法来配置请求级别的安全细节
                //对于静态路径不进行拦截
                .antMatchers( "/css/**","/js/**","/img/**","/plugins/**").permitAll()
        ;

        //设置json格式实现异步登录
        http.addFilterAt(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

        // 禁用缓存
        http
                .headers().cacheControl();

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //配置认证方式
        auth.userDetailsService(myUserDetailsService);
    }

    /**
     * 注册加密类
     * @return 加密类bean
     */
    //todo 先使用明文存储，方便测试，后期再释放注释使用加密密文存储
//    @Bean
//    public BCryptPasswordEncoder bCryptPasswordEncoder(){
//        return new BCryptPasswordEncoder();
//    }
    @Bean
    public PasswordEncoder passwordEncoder(){
        //todo 空加密，即不加密，方便测试，后续删除，替换为BCryptPasswordEncoder
        return NoOpPasswordEncoder.getInstance();
    }

    /**
     * 注入自定义json解析登录
     * @return CustomAuthenticationFilter对象
     * @throws Exception
     */
    @Bean
    CustomAuthenticationFilter customAuthenticationFilter() throws Exception {
        CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
        // 登录成功
        filter.setAuthenticationSuccessHandler(loginSuccessHandler);
        // 登录失败
        filter.setAuthenticationFailureHandler(loginFailureHandler);
        filter.setFilterProcessesUrl("/user/login");
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }



}
